using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GGameFramework.Core.Pool
{
    /// <summary>
    /// 引用类型对象池基类
    /// </summary>
    public abstract class ReferenceObjectPool<T> : IReferencePool<T> where T : IReference//ReferencePoolable
    {
        protected readonly Stack<T> _pool = new Stack<T>();
        protected readonly HashSet<T> _activeObjects = new HashSet<T>(); // 防止重复回收
        protected readonly IPoolingStrategy _strategy;
        protected readonly Func<T> _createFunc;
        protected readonly Action<T> _onSpawn;
        protected readonly Action<T> _onRecycle;
        protected readonly Action<T> _onDestroy;

        public Type PoolType => typeof(T);
        public int Count => _pool.Count;
        public int Capacity { get; protected set; }
        public PoolStatistics Statistics { get; private set; } = new PoolStatistics();
        
        protected ReferenceObjectPool(
            Func<T> createFunc, 
            Action<T> onSpawn = null, 
            Action<T> onRecycle = null, 
            Action<T> onDestroy = null,
            IPoolingStrategy strategy = null,
            int initialCapacity = 10)
        {
            _createFunc = createFunc ?? throw new ArgumentNullException(nameof(createFunc));
            _onSpawn = onSpawn;
            _onRecycle = onRecycle;
            _onDestroy = onDestroy;
            _strategy = strategy ?? new FixedSizePoolingStrategy();
            Capacity = initialCapacity;

            Prewarm(initialCapacity);
        }

        /// <summary>
        /// 预热对象池(预加载)
        /// </summary>
        public void Prewarm(int count)
        {
            for (int i = 0; i < count; i++)
            {
                _pool.Push(CreateNew());
            }
        }

        /// <summary>
        /// 异步分帧加载
        /// </summary>
        public IEnumerator PrewarmAsync(int count, int perFrame = 5) 
        {
            int created = 0;
            while (created < count) 
            {
                for (int i = 0; i < perFrame && created < count; i++) 
                {
                    _pool.Push(CreateNew());
                    created++;
                }
                yield return null;
            }
        }
        
        /// <summary>
        /// 创建新对象
        /// </summary>
        protected virtual T CreateNew()
        {
            return _createFunc();
        }

        /// <summary>
        /// 销毁对象
        /// </summary>
        protected virtual void DestroyObject(T obj)
        {
            if (obj != null)
            {
                _onDestroy?.Invoke(obj);
                _activeObjects.Remove(obj);
            }
        }

        public virtual T Spawn()
        {
            T obj;
            if (_pool.Count > 0)
            {
                obj = _pool.Pop();
            }
            else
            {
                obj = CreateNew();
                Statistics.PoolOverflows++;
            }

            // 添加到活跃对象集合
            _activeObjects.Add(obj);

            _onSpawn?.Invoke(obj);
            if (obj is IPoolable poolable) poolable.OnSpawn();
            
            Statistics.TotalSpawned++;
            Statistics.MaxConcurrent = Mathf.Max(Statistics.MaxConcurrent, Statistics.TotalSpawned - Statistics.TotalRecycled);
            
            return obj;
        }

        public virtual void Recycle(T obj)
        {
            if (obj == null) return;

            // 检查是否已经在池中或已经被回收
            if (!_activeObjects.Contains(obj))
            {
                Debug.LogWarning($"Object {obj} is already recycled or not from this pool");
                return;
            }

            _onRecycle?.Invoke(obj);
            
            if (obj is IPoolable poolable) 
                poolable.OnRecycle();
            
            // 从活跃对象集合中移除
            _activeObjects.Remove(obj);
            
            if (_strategy.ShouldDestroyObject(this, Count))
            {
                DestroyObject(obj);
            }
            else
            {
                _pool.Push(obj);
            }
            Statistics.TotalRecycled++;
        }

        public virtual void Clear()
        {
            // 清理池中的对象
            while (_pool.Count > 0)
            {
                var obj = _pool.Pop();
                DestroyObject(obj);
            }
            _pool.Clear();
            
            // 清理活跃对象
            foreach (var obj in _activeObjects.ToList())
            {
                DestroyObject(obj);
            }
            _activeObjects.Clear();
        }
        
        public void HandleStrategy() 
        {
            _strategy?.HandlePoolSize(this);
        }
        
        /// <summary>
        /// 获取所有池中对象（用于调试和统计）
        /// </summary>
        public List<T> GetAllPooledObjects()
        {
            return _pool.ToList();
        }
        
        /// <summary>
        /// 获取所有活跃对象（用于调试和统计）
        /// </summary>
        public List<T> GetAllActiveObjects()
        {
            return _activeObjects.ToList();
        }
    }

    /// <summary>
    /// GameObject对象池基类
    /// </summary>
    public abstract class GameObjectPool<T> : IGameObjectPool<T> where T : GameObjectPoolable
    {
        protected readonly Stack<T> _pool = new Stack<T>();
        protected readonly HashSet<T> _activeObjects = new HashSet<T>(); // 防止重复回收
        protected readonly IPoolingStrategy _strategy;
        protected readonly Func<T> _createFunc;
        protected readonly Action<T> _onSpawn;
        protected readonly Action<T> _onRecycle;
        protected readonly Action<T> _onDestroy;
        protected readonly Transform _poolRoot;

        public Type PoolType => typeof(T);
        public int Count => _pool.Count;
        public int Capacity { get; protected set; }
        public PoolStatistics Statistics { get; private set; } = new PoolStatistics();
        
        protected GameObjectPool(
            Func<T> createFunc, 
            Action<T> onSpawn = null, 
            Action<T> onRecycle = null, 
            Action<T> onDestroy = null,
            IPoolingStrategy strategy = null,
            int initialCapacity = 10,
            Transform poolRoot = null)
        {
            _createFunc = createFunc ?? throw new ArgumentNullException(nameof(createFunc));
            _onSpawn = onSpawn;
            _onRecycle = onRecycle;
            _onDestroy = onDestroy;
            _strategy = strategy ?? new FixedSizePoolingStrategy();
            _poolRoot = poolRoot;
            Capacity = initialCapacity;

            Prewarm(initialCapacity);
        }

        /// <summary>
        /// 预热对象池
        /// </summary>
        public void Prewarm(int count)
        {
            for (int i = 0; i < count; i++)
            {
                var obj = CreateNew();
                obj.gameObject.SetActive(false);
                _pool.Push(obj);
            }
        }

        /// <summary>
        /// 异步分帧加载
        /// </summary>
        public IEnumerator PrewarmAsync(int count, int perFrame = 5) 
        {
            int created = 0;
            while (created < count) 
            {
                for (int i = 0; i < perFrame && created < count; i++) 
                {
                    var obj = CreateNew();
                    obj.gameObject.SetActive(false);
                    _pool.Push(obj);
                    created++;
                }
                yield return null;
            }
        }
        
        /// <summary>
        /// 创建新对象
        /// </summary>
        protected virtual T CreateNew()
        {
            var obj = _createFunc();
            
            // 设置父级为池根节点
            if (_poolRoot != null)
            {
                obj.transform.SetParent(_poolRoot);
            }
            
            return obj;
        }

        /// <summary>
        /// 销毁对象
        /// </summary>
        protected virtual void DestroyObject(T obj)
        {
            if (obj != null)
            {
                _onDestroy?.Invoke(obj);
                _activeObjects.Remove(obj);
                
                if (obj.gameObject != null)
                {
                    UnityEngine.Object.Destroy(obj.gameObject);
                }
            }
        }

        public virtual T Spawn()
        {
            T obj;
            if (_pool.Count > 0)
            {
                obj = _pool.Pop();
            }
            else
            {
                obj = CreateNew();
                Statistics.PoolOverflows++;
            }

            // 添加到活跃对象集合
            _activeObjects.Add(obj);

            // 激活GameObject
            obj.gameObject.SetActive(true);
            
            _onSpawn?.Invoke(obj);
            obj.OnSpawn();
            
            Statistics.TotalSpawned++;
            Statistics.MaxConcurrent = Mathf.Max(Statistics.MaxConcurrent, Statistics.TotalSpawned - Statistics.TotalRecycled);
            
            return obj;
        }

        public virtual void Recycle(T obj)
        {
            if (obj == null) return;

            // 检查是否已经在池中或已经被回收
            if (!_activeObjects.Contains(obj))
            {
                Debug.LogWarning($"GameObject {obj.name} is already recycled or not from this pool");
                return;
            }

            // 关闭GameObject
            obj.gameObject.SetActive(false);
            
            _onRecycle?.Invoke(obj);
            obj.OnRecycle();
            
            // 从活跃对象集合中移除
            _activeObjects.Remove(obj);
            
            if (_strategy.ShouldDestroyObject(this, Count))
            {
                DestroyObject(obj);
            }
            else
            {
                _pool.Push(obj);
            }
            Statistics.TotalRecycled++;
        }

        public virtual void Clear()
        {
            // 清理池中的对象
            while (_pool.Count > 0)
            {
                var obj = _pool.Pop();
                DestroyObject(obj);
            }
            _pool.Clear();
            
            // 清理活跃对象
            foreach (var obj in _activeObjects.ToList())
            {
                DestroyObject(obj);
            }
            _activeObjects.Clear();
        }
        
        public void HandleStrategy() 
        {
            _strategy?.HandlePoolSize(this);
        }
        
        /// <summary>
        /// 获取所有池中对象（用于调试和统计）
        /// </summary>
        public List<T> GetAllPooledObjects()
        {
            return _pool.ToList();
        }
        
        /// <summary>
        /// 获取所有活跃对象（用于调试和统计）
        /// </summary>
        public List<T> GetAllActiveObjects()
        {
            return _activeObjects.ToList();
        }
    }
}